#ifndef __BASIC_SKT_H__
#define __BASIC_SKT_H__

#include <basic/sock.h>

__BEGIN_DECLS

struct _skt
{/*{{{*/
    unsigned int local;
    unsigned int listen;
    struct sock_info sock_info;
    SOCKET sock;

    struct _skt_rbuf
    {
        unsigned char *buf;
        int begin, end;
        int size;
    } _rbuf;
    struct _skt_wbuf
    {
        unsigned char *buf;
        int size;
    } _wbuf;
};/*}}}*/
typedef struct _skt *SKT;

/*
 * 客户端连接
 */
extern int  /* 0:成功 -12:获取套接字信息出错
               unix域 -1:套接字分配出错 -2:连接出错
               tcp -3:地址错误 -4:套接字分配出错 -5:主机名解析出错
               -6:IP地址解析出错 -7:设置非阻塞出错 -8:连接出错
               -1:等待出错 -9:获取对方信息出错 -10:等待返回值异常
               -11:重设置阻塞出错 */
skt_connect(
        char *host_addr,    /* [IN] 主机(host:port) unix域(filename)  */
        unsigned int flag,          /* [IN] 标志 FLAG_LOCAL:unix域 */
        int *p_timeout_ms,  /* [IN] 超时(毫秒) [OUT] 剩余时间
                               {NULL或指向负值:无限等待} */
        SKT *pskt           /* [OUT] skt接口 */
        );

/*
 * 服务端监听
 */
extern int  /* 0:成功
               unix: -1:套接字分配出错
               tcp -2:套接字分配出错 -3:设置套接字属性出错
               -4:bind出错 -5:listen出错 */
skt_listen(
        char *port,         /* [IN] 端口或unix域路径 */
        unsigned int flag,  /* [IN] 标志 FLAG_LOCAL:unix域 */
        SKT *pskt           /* [OUT] skt接口 */
        );

/*
 * 服务端接受连接
 */
extern int	/* 0:成功 -1:等待出错 -2:accept出错 -3:获取套接字信息出错 */
skt_accept(
        SKT skt,            /* [IN] 服务器监听套接字 */
        int *p_timeout_ms,  /* [IN] 超时(毫秒) [OUT] 剩余时间
                               {NULL或指向负值:无限等待} */
        SKT *pskt           /* [OUT] skt接口 */
        );

/*
 * 关闭
 */
extern void
skt_close(
        SKT skt             /* [IN] skt接口 */
        );

/*
 * 生成UNIX域skt接口对
 */
extern int	/* 0:成功 -1:生成套接字对出错 -2:获取套接字信息出错 */
skt_pair(
        SKT sockpair[2]     /* [OUT] UNIX域skt接口对 */
        );

/*
 * 读缓冲区中数据长度
 */
extern int  /* 数据长度 */
skt_readbuf_size(
        SKT skt             /* [IN] 接口 */
        );

#define TEXTEND     CRLF"."CRLF

enum _skt_r_flag
{
    SKT_R_SIZE=1,
    SKT_R_WRAP,
    SKT_R_LINE,
    SKT_R_TEXT,
    SKT_R_RAW
};

/*
 * 读skt
 */
extern int  /* 读出的数据长度
               -1:等待出错 -2:recv出错
               WRAP -3:消息头包含无效长度值
               LINE -4:行长度超过限度 */
skt_read(
        SKT skt,            /* [IN] skt句柄 */
        unsigned char *readbuf, /* [OUT] 读消息缓冲区 */
        int *read_size,     /* [OUT] 读消息大小 */
        unsigned int flag,  /* [IN] 标志 enum _skt_r_flag */
        int *p_timeout_ms   /* [IN] 超时(毫秒) [OUT] 剩余时间
                               {NULL或指向负值:无限等待} */
        );

/*
 * 读skt(分配读缓冲区)
 */
extern int  /* 读出的数据长度
               -1:等待出错 -2:recv出错
               WRAP -3:消息头包含无效长度值
               LINE -4:行长度超过限度 */
skt_read_alloc(
        SKT skt,            /* [IN] skt句柄 */
        unsigned char **preadbuf,   /* [OUT] 读消息缓冲区指针地址 */
        int *read_size,     /* [OUT] 读消息大小 */
        unsigned int flag,  /* [IN] 标志 enum _skt_r_flag */
        int *p_timeout_ms   /* [IN] 超时(毫秒) [OUT] 剩余时间
                               {NULL或指向负值:无限等待} */
        );

enum _skt_w_flag
{
    SKT_W_SIZE=1,
    SKT_W_WRAP
};

/*
 * 写skt
 */
extern int  /* 写入的数据长度
               -1:等待出错 -2:send出错 */
skt_write(
        SKT skt,            /* [IN] 接口 */
        unsigned char *writebuf,    /* [IN] 写消息缓冲区 */
        int *write_size,    /* [IN,OUT] 写消息大小 */
        unsigned int flag,  /* [IN] 标志 enum _skt_w_flag */
        int *p_timeout_ms   /* [IN] 超时(毫秒) [OUT] 剩余时间
                               {NULL或指向负值:无限等待} */
        );

/*
 * 调用
 */
extern int  /* 0:成功
               -1:写入等待出错 -2:send出错
               -3:读出等待出错 -4:recv出错
               WRAP -5:消息头包含无效长度值
               LINE -6:行长度超过限度 */
skt_call(
        SKT skt,            /* [IN] 接口 */
        unsigned char *writebuf,/* [IN] 写消息缓冲区 */
        int *writesize,     /* [IN,OUT] 写消息大小 */
        unsigned int wflag, /* [IN] 标志 enum _skt_w_flag */
        unsigned char *readbuf, /* [OUT] 读消息缓冲区指针地址 */
        int *readsize,      /* [OUT] 读消息大小 */
        unsigned int rflag, /* [IN] 标志 enum _skt_r_flag */
        int *p_timeout_ms   /* [IN] 超时(毫秒) [OUT] 剩余时间
                               {NULL或指向负值:无限等待} */
        );

__END_DECLS

#endif
